#include "utils.h"
xio *iioo = NULL;

using namespace std;

xio::xio(uint beep_on, uint help_on, uint dbg_on, bool execMode)
{
	ICMD_BEEP   =  beep_on;
	HELP_MSG    =  help_on;
	DBG_MSG     =  dbg_on;
	mode        =  execMode;
}

lexResult xio::lex(std::string target, std::string tokens, int hml)
{
    dbgMsg("Lexer procedure initiated with params: ", target+"->"+"\""+tokens+"\"");

	tokens+="\r\n";

    int lastsep = 0;
    int lexes = 0;
	bool found = false;
    lexResult lr;

    lr.origin = stripN(target);
    lr.tokens = tokens;
    target = stripN(target);

	for(uint i = 0; i<=tokens.size()-1; i++)
	{
		if(target.find(tokens.at(i)) != FIND_ERROR_CODE)
		{
			found = true;
			break;
		}
		else
			found = false;
	}

	if(!found)
	{
		lr.result.push_back(lr.origin);
		return lr;
	}		

    for(uint i = 0; i<=target.size()-1; i++)
    {
        for(uint j = 0; j<=tokens.size()-1; j++)
        {
			if(i == target.size()-1)
			{
				lr.result.push_back(target.substr(lastsep, target.size()-1));
				lexes++;
				return lr;
			}
            if(target[i] == tokens[j])
            {
				if(lexes == hml)
                {
                    std::string lstr = lr.result.at(lr.result.size()-1) + target.substr(lastsep, lr.origin.size());
                    lr.result.push_back(lstr);
                    return lr;
                }
				else
				{
					lr.result.push_back(target.substr(lastsep, i));
					lastsep = i+1;
					lexes++;
				}
            }
        }
    }

    if(lr.result.size() == 0)
        lr.result.push_back(target);

    return lr;
}

std::string xio::stripN(const std::string &target)
{
    if(target[target.size()] == '\n')
        return target.substr(0, target.size()-1);
    else
    {
        dbgMsg("No \\n's found", "");
        return target;
    }
}

void xio::dbgMsg(std::string s1, std::string s2)
{
	if(mode == AUTO)
		return;

    if(!DBG_MSG)
        return;

    cout << DBG_HEAD;
    cout << s1;
    cout << s2;
    cout << "\n";
}

void xio::cmpMsg(std::string str)
{
	if(mode == AUTO)
		return;

    cout << CMP_HEAD;
    cout << str;
    cout << "\n";

	if(ICMD_BEEP)
		cout << "\a";
}

void xio::hlpMsg(std::string msg, bool byp)
{
	if(mode == AUTO)
		return;

    if(byp)
    {
        cout << HELP_HEAD;
        cout << msg;
        cout << "\n";
    }
	else
		return;

	if(!io()->isHelp_on())
        return;

	if(io()->isHelp_on())
    {
        cout << HELP_HEAD;
        cout << msg;
        cout << "\n";
    }
}

void xio::setExecType(bool t)
{
	if(t == AUTO)
	{
		mode = AUTO;
	}
	else
	{
		mode = INTR;
	}
}

uint xio::isDebug_on()
{
	return this->DBG_MSG;
}

uint xio::isHelp_on()
{
	return this->HELP_MSG;
}

void xio::debug_on()
{
	DBG_MSG = 1;
}

void xio::debug_off()
{
	DBG_MSG = 0;
}

void xio::help_on()
{
	HELP_MSG = 1;
}

void xio::help_off()
{
	HELP_MSG = 0;
}

void xio::icmd_beep_off()
{
	ICMD_BEEP = 0;
}

void xio::icmd_beep_on()
{
	ICMD_BEEP = 1;
}

bool xio::xType()
{
	return mode;
}

xio *io()
{
	static xio *inout = iioo;
	return inout;
}

void setIO(xio xotr)
{
	iioo = new xio(xotr);
}

std::string xio::trim(const std::string &target)
{
	std::string t = stripN(target);

	uint i = 0;
	while(t[i] == ' ')
	{
		i++;
	}
	t = t.substr(i,t.size()-1);

	i = t.size()-1;
	
	while(t[i] == ' ')
	{
		i--;
	}

	t = t.substr(0, i);
	return t;
}

std::string xio::killMultiSpaces(const std::string &target)
{
	char lastchar = -1;
	std::string t = trim(target), r;

	for(uint i = 0; i < t.size(); i++)
	{
		if(i > 0)
			lastchar = t[i-1];

		if(lastchar > 0)
			if(t[i] != lastchar)
				r += t[i];
	}

	return r;
}

std::string xio::deleteChar(std::string target, const std::string tokens)
{
	dbgMsg("Lexer procedure initiated with params: ", target+"->"+"\""+tokens+"\"");

    int lastsep = 0;
    int lexes = 0;
	bool found = false;
	std::string lr;

    target = killMultiSpaces(target);

	for(uint i = 0; i < tokens.size(); i++)
	{
		if(target.find(tokens.at(i)) != FIND_ERROR_CODE)
		{
			found = true;
			break;
		}
		else
			found = false;
	}

	if(!found)
	{
		lr = target;
		return lr;
	}		

    for(uint i = 0; i < target.size(); i++)
    {
        for(uint j = 0; j < tokens.size(); j++)
        {
            if(target[i] == tokens[j])
            {
				//nop
            }
			else
			{
				lr += target[i];
			}
        }
    }

    if(lr.size() == 0)
        lr = target;

    return lr;
}
